/*globals svgEditor, svgedit, svgCanvas, $*/
/*jslint vars: true, eqeq: true, todo: true*/
/*
 * ext-foreignobject.js
 *
 * Licensed under the Apache License, Version 2
 *
 * Copyright(c) 2010 Jacques Distler
 * Copyright(c) 2010 Alexis Deveria
 *
 */

svgEditor.addExtension("foreignObject", function(S) {
	var NS = svgedit.NS,
		Utils = svgedit.utilities,
		svgcontent = S.svgcontent,
		addElem = S.addSvgElementFromJson,
		selElems,
		editingforeign = false,
		svgdoc = S.svgroot.parentNode.ownerDocument,
		started,
		newFO;

	var properlySourceSizeTextArea = function () {
		// TODO: remove magic numbers here and get values from CSS
		var height = $('#svg_source_container').height() - 80;
		$('#svg_source_textarea').css('height', height);
	};

	function showPanel(on) {
		var fc_rules = $('#fc_rules');
		if(!fc_rules.length) {
			fc_rules = $('<style id="fc_rules"></style>').appendTo('head');
		}
		fc_rules.text(!on?"":" #tool_topath { display: none !important; }");
		$('#foreignObject_panel').toggle(on);
	}

	function toggleSourceButtons(on) {
		$('#tool_source_save, #tool_source_cancel').toggle(!on);
		$('#foreign_save, #foreign_cancel').toggle(on);
	}

	// Function: setForeignString(xmlString, elt)
	// This function sets the content of element elt to the input XML.
	//
	// Parameters:
	// xmlString - The XML text.
	// elt - the parent element to append to
	//
	// Returns:
	// This function returns false if the set was unsuccessful, true otherwise.
	function setForeignString(xmlString) {
		var elt = selElems[0];
		try {
			// convert string into XML document
			var newDoc = Utils.text2xml('<svg xmlns="' + NS.SVG + '" xmlns:xlink="' + NS.XLINK + '">' + xmlString + '</svg>');
			// run it through our sanitizer to remove anything we do not support
			S.sanitizeSvg(newDoc.documentElement);
			elt.parentNode.replaceChild(svgdoc.importNode(newDoc.documentElement.firstChild, true), elt);
			S.call("changed", [elt]);
			svgCanvas.clearSelection();
		} catch(e) {
			console.log(e);
			return false;
		}

		return true;
	}

	function showForeignEditor() {
		var elt = selElems[0];
		if (!elt || editingforeign) {return;}
		editingforeign = true;
		toggleSourceButtons(true);
		elt.removeAttribute('fill');

		var str = S.svgToString(elt, 0);
		$('#svg_source_textarea').val(str);
		$('#svg_source_editor').fadeIn();
		properlySourceSizeTextArea();
		$('#svg_source_textarea').focus();
	}

	function setAttr(attr, val) {
		svgCanvas.changeSelectedAttribute(attr, val);
		S.call("changed", selElems);
	}

	return {
		name: "foreignObject",
		svgicons: svgEditor.curConfig.extPath + "foreignobject-icons.xml",
		buttons: [{
			id: "tool_foreign",
			type: "mode",
			title: "Foreign Object Tool",
			events: {
				'click': function() {
					svgCanvas.setMode('foreign');
				}
			}
		},{
			id: "edit_foreign",
			type: "context",
			panel: "foreignObject_panel",
			title: "Edit ForeignObject Content",
			events: {
				'click': function() {
					showForeignEditor();
				}
			}
		}],

		context_tools: [{
			type: "input",
			panel: "foreignObject_panel",
			title: "Change foreignObject's width",
			id: "foreign_width",
			label: "w",
			size: 3,
			events: {
				change: function() {
					setAttr('width', this.value);
				}
			}
		},{
			type: "input",
			panel: "foreignObject_panel",
			title: "Change foreignObject's height",
			id: "foreign_height",
			label: "h",
			events: {
				change: function() {
					setAttr('height', this.value);
				}
			}
		}, {
			type: "input",
			panel: "foreignObject_panel",
			title: "Change foreignObject's font size",
			id: "foreign_font_size",
			label: "font-size",
			size: 2,
			defval: 16,
			events: {
				change: function() {
					setAttr('font-size', this.value);
				}
			}
		}

		],
		callback: function() {
			$('#foreignObject_panel').hide();

			var endChanges = function() {
				$('#svg_source_editor').hide();
				editingforeign = false;
				$('#svg_source_textarea').blur();
				toggleSourceButtons(false);
			};

			// TODO: Needs to be done after orig icon loads
			setTimeout(function() {
				// Create source save/cancel buttons
				var save = $('#tool_source_save').clone()
					.hide().attr('id', 'foreign_save').unbind()
					.appendTo("#tool_source_back").click(function() {

						if (!editingforeign) {return;}

						if (!setForeignString($('#svg_source_textarea').val())) {
							$.confirm("Errors found. Revert to original?", function(ok) {
								if(!ok) {return false;}
								endChanges();
							});
						} else {
							endChanges();
						}
						// setSelectMode();
					});

				var cancel = $('#tool_source_cancel').clone()
					.hide().attr('id', 'foreign_cancel').unbind()
					.appendTo("#tool_source_back").click(function() {
						endChanges();
					});
			}, 3000);
		},
		mouseDown: function(opts) {
			var e = opts.event;

			if(svgCanvas.getMode() == "foreign") {

				started = true;
				newFO = S.addSvgElementFromJson({
					"element": "foreignObject",
					"attr": {
						"x": opts.start_x,
						"y": opts.start_y,
						"id": S.getNextId(),
						"font-size": 16, //cur_text.font_size,
						"width": "48",
						"height": "20",
						"style": "pointer-events:inherit"
					}
				});
				var m = svgdoc.createElementNS(NS.MATH, 'math');
				m.setAttributeNS(NS.XMLNS, 'xmlns', NS.MATH);
				m.setAttribute('display', 'inline');
				var mi = svgdoc.createElementNS(NS.MATH, 'mi');
				mi.setAttribute('mathvariant', 'normal');
				mi.textContent = "\u03A6";
				var mo = svgdoc.createElementNS(NS.MATH, 'mo');
				mo.textContent = "\u222A";
				var mi2 = svgdoc.createElementNS(NS.MATH, 'mi');
				mi2.textContent = "\u2133";
				m.appendChild(mi);
				m.appendChild(mo);
				m.appendChild(mi2);
				newFO.appendChild(m);
				return {
					started: true
				};
			}
		},
		mouseUp: function(opts) {
			var e = opts.event;
			if(svgCanvas.getMode() == "foreign" && started) {
				var attrs = $(newFO).attr(["width", "height"]);
				var keep = (attrs.width != 0 || attrs.height != 0);
				svgCanvas.addToSelection([newFO], true);

				return {
					keep: keep,
					element: newFO
				};

			}

		},
		selectedChanged: function(opts) {
			// Use this to update the current selected elements
			selElems = opts.elems;

			var i = selElems.length;

			while(i--) {
				var elem = selElems[i];
				if(elem && elem.tagName === 'foreignObject') {
					if(opts.selectedElement && !opts.multiselected) {
						$('#foreign_font_size').val(elem.getAttribute("font-size"));
						$('#foreign_width').val(elem.getAttribute("width"));
						$('#foreign_height').val(elem.getAttribute("height"));
						showPanel(true);
					} else {
						showPanel(false);
					}
				} else {
					showPanel(false);
				}
			}
		},
		elementChanged: function(opts) {
			var elem = opts.elems[0];
		}
	};
});
